Handle broken grabs.
authorMatthias Clasen <mclasen@redhat.com>
Thu, 30 Jun 2005 03:35:30 +0000 (03:35 +0000)
committerMatthias Clasen <matthiasc@src.gnome.org>
Thu, 30 Jun 2005 03:35:30 +0000 (03:35 +0000)
2005-06-29  Matthias Clasen  <mclasen@redhat.com>

        * gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
        grabs.

        * gtk/gtkrange.c (gtk_range_grab_broken): Handle broken
        grabs.

        * gdk/gdkevents.h: Add a boolean to specify wether the broken
        grab was implicit.

        * gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed):
        As the documentation states, don't return TRUE for
        implicit grabs.

        * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
        a boolean field to store wether a pointer grab is implicit.

        * gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event):
        Track implicit grabs.

        * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
        _gdk_xgrab_check_button_event for button events.

ChangeLog
ChangeLog.pre-2-10
ChangeLog.pre-2-8
gdk/gdkevents.h
gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkdisplay-x11.h
gdk/x11/gdkevents-x11.c
gdk/x11/gdkmain-x11.c
gtk/gtkbutton.c
gtk/gtkrange.c

index 877b9a591af9cbc79024c6332a0d3d2624747ed2..380371f83f41ae5257a33171b071eabece7d3ce2 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,27 @@
+2005-06-29  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
+       grabs.
+
+       * gtk/gtkrange.c (gtk_range_grab_broken): Handle broken 
+       grabs.
+
+       * gdk/gdkevents.h: Add a boolean to specify wether the broken
+       grab was implicit.
+
+       * gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed): 
+       As the documentation states, don't return TRUE for
+       implicit grabs.
+
+       * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
+       a boolean field to store wether a pointer grab is implicit.
+
+       * gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event): 
+       Track implicit grabs.
+
+       * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
+       _gdk_xgrab_check_button_event for button events.
+
 2005-06-28  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2): 
index 877b9a591af9cbc79024c6332a0d3d2624747ed2..380371f83f41ae5257a33171b071eabece7d3ce2 100644 (file)
@@ -1,3 +1,27 @@
+2005-06-29  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
+       grabs.
+
+       * gtk/gtkrange.c (gtk_range_grab_broken): Handle broken 
+       grabs.
+
+       * gdk/gdkevents.h: Add a boolean to specify wether the broken
+       grab was implicit.
+
+       * gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed): 
+       As the documentation states, don't return TRUE for
+       implicit grabs.
+
+       * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
+       a boolean field to store wether a pointer grab is implicit.
+
+       * gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event): 
+       Track implicit grabs.
+
+       * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
+       _gdk_xgrab_check_button_event for button events.
+
 2005-06-28  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2): 
index 877b9a591af9cbc79024c6332a0d3d2624747ed2..380371f83f41ae5257a33171b071eabece7d3ce2 100644 (file)
@@ -1,3 +1,27 @@
+2005-06-29  Matthias Clasen  <mclasen@redhat.com>
+
+       * gtk/gtkbutton.c (gtk_button_grab_broken): Handle broken
+       grabs.
+
+       * gtk/gtkrange.c (gtk_range_grab_broken): Handle broken 
+       grabs.
+
+       * gdk/gdkevents.h: Add a boolean to specify wether the broken
+       grab was implicit.
+
+       * gdk/x11/gdkdisplay-x11.c (gdk_display_pointer_is_grabbed): 
+       As the documentation states, don't return TRUE for
+       implicit grabs.
+
+       * gdk/x11/gdkdisplay-x11.h (struct _GdkDisplayX11): Add
+       a boolean field to store wether a pointer grab is implicit.
+
+       * gdk/x11/gdkmain-x11.c (_gdk_xgrab_check_button_event): 
+       Track implicit grabs.
+
+       * gdk/x11/gdkevents-x11.c (gdk_event_translate): Call
+       _gdk_xgrab_check_button_event for button events.
+
 2005-06-28  Matthias Clasen  <mclasen@redhat.com>
 
        * gtk/gtkiconview.c (gtk_icon_view_calculate_item_size2): 
index bf4db6ead107db345f928c43f64c6f4f03d27335..67708682ab7b61c51f1adc1361af2ea4b48502b6 100644 (file)
@@ -1,3 +1,4 @@
+
 #ifndef __GDK_EVENTS_H__
 #define __GDK_EVENTS_H__
 
@@ -436,6 +437,7 @@ struct _GdkEventGrabBroken {
   GdkWindow *window;
   gint8 send_event;
   gboolean keyboard;
+  gboolean implicit;
   GdkWindow *grab_window;
 };
 
index 66cdc828004c7a0648c3dd2dae90f0753faded41..133909dd2f769308968e60e51ce49b758e08117e 100644 (file)
@@ -539,7 +539,8 @@ gdk_display_pointer_is_grabbed (GdkDisplay * display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
   
-  return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL);
+  return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
+         !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
 }
 
 /**
index 3e69fa5644f600e3ac460a62fb7721abe0023b82..24f317788f9088d1cc6bc143bca636d132eac3df 100644 (file)
@@ -88,6 +88,7 @@ struct _GdkDisplayX11
   GdkWindowObject *pointer_xgrab_window;
   gulong pointer_xgrab_serial;
   gboolean pointer_xgrab_owner_events;
+  gboolean pointer_xgrab_implicit;
   guint32 pointer_xgrab_time;
 
   GdkWindowObject *keyboard_xgrab_window;
index 97b027c87009fbe04c67d7204fc3bd0d7e2f2186..4a45cf6984f8d7d7dcc8c442f633baa2a41a010c 100644 (file)
@@ -1132,6 +1132,8 @@ gdk_event_translate (GdkDisplay *display,
        }
 
       set_user_time (window, event);
+
+      _gdk_xgrab_check_button_event (window, xevent);
       break;
       
     case ButtonRelease:
@@ -1170,7 +1172,8 @@ gdk_event_translate (GdkDisplay *display,
       event->button.device = display->core_pointer;
 
       set_screen_from_root (display, event, xevent->xbutton.root);
-      
+
+      _gdk_xgrab_check_button_event (window, xevent);
       break;
       
     case MotionNotify:
index b92bd6433042bf149923cc389b0f318e2bc41f85..985b2b5dcee559547e86ba505d4328a13e9b79d8 100644 (file)
@@ -139,8 +139,9 @@ gdk_x11_convert_grab_status (gint status)
 
 static void
 generate_grab_broken_event (GdkWindow *window,
-                           GdkWindow *grab_window,
-                           gboolean   keyboard)
+                           gboolean   keyboard,
+                           gboolean   implicit,
+                           GdkWindow *grab_window)
 {
   GdkEvent event;
   
@@ -148,6 +149,7 @@ generate_grab_broken_event (GdkWindow *window,
   event.grab_broken.window = window;
   event.grab_broken.send_event = 0;
   event.grab_broken.keyboard = keyboard;
+  event.grab_broken.implicit = implicit;
   event.grab_broken.grab_window = grab_window;
 
   gdk_event_put (&event);
@@ -254,14 +256,16 @@ gdk_pointer_grab (GdkWindow *       window,
     {
       GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
       if (display_x11->pointer_xgrab_window != NULL &&
-         display_x11->pointer_xgrab_window != window)
+         display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
        generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                   window, FALSE);
+                                   FALSE, display_x11->pointer_xgrab_implicit,
+                                   window);
 
       display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
       display_x11->pointer_xgrab_serial = serial;
       display_x11->pointer_xgrab_owner_events = owner_events;
       display_x11->pointer_xgrab_time = time;
+      display_x11->pointer_xgrab_implicit = FALSE;
     }
 
   return gdk_x11_convert_grab_status (return_val);
@@ -357,9 +361,9 @@ gdk_keyboard_grab (GdkWindow *         window,
     {
       GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
       if (display_x11->keyboard_xgrab_window != NULL &&
-         display_x11->keyboard_xgrab_window != window)
+         display_x11->keyboard_xgrab_window != (GdkWindowObject *)window)
        generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
-                                   window, TRUE);
+                                   TRUE, FALSE, window);
       
       display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
       display_x11->keyboard_xgrab_serial = serial;
@@ -435,7 +439,8 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
       if (tmp)
        {         
          generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                     NULL, FALSE);
+                                     FALSE, display_x11->pointer_xgrab_implicit, 
+                                     NULL);
          display_x11->pointer_xgrab_window = NULL;  
        }
     }
@@ -453,7 +458,7 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
       if (tmp)
        {
          generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
-                                     NULL, TRUE);
+                                     TRUE, FALSE, NULL);
          display_x11->keyboard_xgrab_window = NULL;  
        }
     }
@@ -474,18 +479,58 @@ _gdk_xgrab_check_destroy (GdkWindow *window)
   if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
     {
       generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                 NULL, FALSE);
+                                 FALSE, display_x11->pointer_xgrab_implicit,
+                                 NULL);
       display_x11->pointer_xgrab_window = NULL;
     }
 
   if ((GdkWindowObject *)window ==  display_x11->keyboard_xgrab_window)
     {
       generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
-                                 NULL, TRUE);
+                                 TRUE, FALSE, NULL);
       display_x11->keyboard_xgrab_window = NULL;
     }
 }
 
+/**
+ * _gdk_xgrab_check_button_event:
+ * @window: a #GdkWindow
+ * @event: an XEvent of type ButtonPress or ButtonRelease
+ * 
+ * Checks to see if a button event starts or ends an implicit grab.
+ **/
+void
+_gdk_xgrab_check_button_event (GdkWindow *window, 
+                              XEvent *xevent)
+{
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+  
+  /* track implicit grabs for button presses */
+  switch (xevent->type)
+    {
+    case ButtonPress:
+      if (!display_x11->pointer_xgrab_window)
+       {
+         display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
+         display_x11->pointer_xgrab_serial = xevent->xany.serial;
+         display_x11->pointer_xgrab_owner_events = FALSE;
+         display_x11->pointer_xgrab_time = xevent->xbutton.time;
+         display_x11->pointer_xgrab_implicit = TRUE;     
+       }
+      break;
+    case ButtonRelease:
+      if (display_x11->pointer_xgrab_window &&
+         display_x11->pointer_xgrab_implicit &&
+         (xevent->xbutton.state & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
+       {
+         display_x11->pointer_xgrab_window = NULL;
+       }
+      break;
+    default:
+      g_assert_not_reached ();
+    }
+}
+
 void
 _gdk_windowing_display_set_sm_client_id (GdkDisplay  *display,
                                         const gchar *sm_client_id)
index 984d99adca4f13f2192616b15bb6ff69a294917c..dbf34fb144a5f3fa68299ddecc1cee7790e25c1d 100644 (file)
@@ -112,6 +112,8 @@ static gint gtk_button_button_press   (GtkWidget        *widget,
                                       GdkEventButton   *event);
 static gint gtk_button_button_release (GtkWidget        *widget,
                                       GdkEventButton   *event);
+static gint gtk_button_grab_broken    (GtkWidget        *widget,
+                                      GdkEventAny      *event);
 static gint gtk_button_key_release    (GtkWidget        *widget,
                                       GdkEventKey      *event);
 static gint gtk_button_enter_notify   (GtkWidget        *widget,
@@ -201,6 +203,7 @@ gtk_button_class_init (GtkButtonClass *klass)
   widget_class->expose_event = gtk_button_expose;
   widget_class->button_press_event = gtk_button_button_press;
   widget_class->button_release_event = gtk_button_button_release;
+  widget_class->grab_broken_event = gtk_button_grab_broken;
   widget_class->key_release_event = gtk_button_key_release;
   widget_class->enter_notify_event = gtk_button_enter_notify;
   widget_class->leave_notify_event = gtk_button_leave_notify;
@@ -1262,6 +1265,29 @@ gtk_button_button_release (GtkWidget      *widget,
   return TRUE;
 }
 
+static gboolean
+gtk_button_grab_broken (GtkWidget   *widget,
+                       GdkEventAny *event)
+{
+  GtkButton *button = GTK_BUTTON (widget);
+  gboolean save_in;
+  
+  /* Simulate a button release without the pointer in the button */
+  if (button->button_down)
+    {
+      save_in = button->in_button;
+      button->in_button = FALSE;
+      gtk_button_released (button);
+      if (save_in != button->in_button)
+       {
+         button->in_button = save_in;
+         gtk_button_update_state (button);
+       }
+    }
+
+  return TRUE;
+}
+
 static gboolean
 gtk_button_key_release (GtkWidget   *widget,
                        GdkEventKey *event)
index d8340eb7c5f79433e0fae78c62f37c47f823f9fe..af337cdf31a08613fc4202edbc1f6a00158c6976 100644 (file)
@@ -124,6 +124,8 @@ static gint gtk_range_enter_notify   (GtkWidget        *widget,
                                       GdkEventCrossing *event);
 static gint gtk_range_leave_notify   (GtkWidget        *widget,
                                       GdkEventCrossing *event);
+static gboolean gtk_range_grab_broken (GtkWidget          *widget,
+                                      GdkEventGrabBroken *event);
 static void gtk_range_grab_notify    (GtkWidget          *widget,
                                      gboolean            was_grabbed);
 static void gtk_range_state_changed  (GtkWidget          *widget,
@@ -244,6 +246,7 @@ gtk_range_class_init (GtkRangeClass *class)
   widget_class->scroll_event = gtk_range_scroll_event;
   widget_class->enter_notify_event = gtk_range_enter_notify;
   widget_class->leave_notify_event = gtk_range_leave_notify;
+  widget_class->grab_broken_event = gtk_range_grab_broken;
   widget_class->grab_notify = gtk_range_grab_notify;
   widget_class->state_changed = gtk_range_state_changed;
   widget_class->style_set = gtk_range_style_set;
@@ -1378,6 +1381,25 @@ stop_scrolling (GtkRange *range)
   gtk_widget_queue_draw (GTK_WIDGET (range));
 }
 
+static gboolean
+gtk_range_grab_broken (GtkWidget          *widget,
+                      GdkEventGrabBroken *event)
+{
+  GtkRange *range = GTK_RANGE (widget);
+
+  if (range->layout->grab_location != MOUSE_OUTSIDE)
+    {
+      if (range->layout->grab_location == MOUSE_SLIDER)
+       update_slider_position (range, range->layout->mouse_x, range->layout->mouse_y);
+      
+      stop_scrolling (range);
+      
+      return TRUE;
+    }
+  
+  return FALSE;
+}
+
 static gint
 gtk_range_button_release (GtkWidget      *widget,
                          GdkEventButton *event)